package xyz.xtt.client.starter.lock;

import java.util.UUID;
import java.util.concurrent.Callable;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;

import lombok.extern.slf4j.Slf4j;
import xyz.xtt.common.exception.NftException;

@Slf4j
public class RedisLock {
	@Autowired
	private StringRedisTemplate stringRedisTemplate;

	public <T> T lock(Callable<T> callable, LockConfig lockConfig, String... redisKey) throws Exception {
		String genKey = lockConfig.genKey(redisKey);
		long seconds = lockConfig.timeUnit().toSeconds(lockConfig.ttl());
		log.info("RedisLock redisKey:[{}], expireTime seconds:{}", genKey, seconds);
		String val = UUID.randomUUID().toString();
		boolean lock = stringRedisTemplate.opsForValue().setIfAbsent(genKey, val, lockConfig.ttl(), lockConfig.timeUnit());
		if (lock) {
			try {
				return callable.call();
			} catch (Exception e) {
				log.info("RedisLock key:{}, ex:{}", genKey, e.getMessage(), e);
				throw e;
			} finally {
				if (val.equals(stringRedisTemplate.opsForValue().get(genKey))) {
					stringRedisTemplate.delete(genKey);
				}
			}
		} else {
			throw new NftException(998, "请求过快，请稍候在试");
		}
	}

}
